/*! \file uart2.c \brief Dual UART driver with buffer support. */
//*****************************************************************************
//
// File Name	: 'uart2.c'
// Title		: Dual UART driver with buffer support
// Author		: Pascal Stang - Copyright (C) 2000-2004
// Created		: 11/20/2000
// Revised		: 07/04/2004
// Version		: 1.0
// Target MCU	: ATMEL AVR Series
// Editor Tabs	: 4
//
// Description	: This is a UART driver for AVR-series processors with two
//		hardware UARTs such as the mega161 and mega128 
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#include <avr/io.h>
#include <avr/interrupt.h>

#include "buffer.h"
#include "uart2.h"
#include "main.h"
#include "timer128.h"
#include "globals.h"
#include "bikirom-ints.h"

typedef struct _typRxBuffer0
{
	unsigned char	uchData[UART0_RX_BUFFER_SIZE];
	unsigned char*	pchWrite;
	unsigned short	ushLength;
	unsigned short	ushBytes;
	void			(*vptrRcvFunc)(void);
} _typRxBuffer0;

static struct _typRxBuffer0 typRxBuffer0;

// UART global variables
// flag variables
volatile uint8_t uartReadyTx[2];
volatile uint8_t uartBufferedTx[2];
volatile uint8_t uartBufferBusy[2];
// receive and transmit buffers
static cBuffer uartRxBuffer[2];
static cBuffer uartTxBuffer[2];
unsigned short uartRxOverflow[2];
unsigned int uartRxBytes[2] = {0,0};

static uint8_t	uartConsultFirstByte = 0;
static uint8_t	uartConsultMode = uConModeStream;

uint8_t uartByPass = 0;
#ifndef UART_BUFFERS_EXTERNAL_RAM
	// using internal ram,
	// automatically allocate space in ram for each buffer
	//static unsigned char uart0RxData[UART0_RX_BUFFER_SIZE];
	static unsigned char uart0TxData[UART0_TX_BUFFER_SIZE];
	static unsigned char uart1RxData[UART1_RX_BUFFER_SIZE];
	static unsigned char uart1TxData[UART1_TX_BUFFER_SIZE];
#endif

typedef void (*voidFuncPtruint8_t)(unsigned char);
volatile static voidFuncPtruint8_t UartRxFunc[2];

//-------------------------------------------------- Global Variables here
static uint8_t uartRxStatus[2] = {0,0};
static uint16_t uartCounter[2] = {0,0};
static uint8_t uartConsultExpected = 0;
static uint32_t uartConsultBitSet = 0;

void uart0_frame_rcv_step0(void);// __attribute__((naked));
void uart0_frame_rcv_step1(void);// __attribute__((naked));
void uart0_frame_rcv_step2(void);// __attribute__((naked));
void uart0_frame_rcv_step3(void);// __attribute__((naked));
void uart0_frame_rcv_step4(void);// __attribute__((naked));
void uart0_frame_rcv_step5(void);// __attribute__((naked));
void uart0_frame_rcv_step6(void);// __attribute__((naked));

// These variables need to be moved to the globals.h section
#define CONSULT_TIMOUT 100

#define UART_CONSULT 1
#define UART_USB 0

// etc etc.. define the parsing for the bit set..

uint8_t getConsultMode(void)
{
	return 	((uartRxStatus[1] >= 0x12) && (uartRxStatus[1] <= 0x30)) ? 1 : 0;
}

void uartSetUartBypass(uint8_t ByPass)
{
	uartByPass = ByPass;
}

void uartInit(void)
{
	// initialize both uarts
	uart0Init();
	uart1Init();
}

void uart0Init(void)
{
	// initialize the buffers
	uart0InitBuffers();
	// initialize user receive handlers
	UartRxFunc[0] = 0;
	// Set the Interrupt Pointer
	//typRxBuffer0.vptrRcvFunc = &uart0_frame_rcv_step0;
	typRxBuffer0.ushBytes = 0;

	// enable RxD/TxD and interrupts
	outb(UCSR0B, BV(RXCIE)|BV(RXEN)|BV(TXEN));

	// set default baud rate
	uartSetBaudRate(0, UART0_DEFAULT_BAUD_RATE); 
	// initialize states
	uartReadyTx[0] = TRUE;
	uartBufferedTx[0] = TRUE;
	// clear overflow count
	uartRxOverflow[0] = 0;

#ifdef INT_RTS
	// Attach to the interrupt
	int_attach(INT_RTS, eIntCtrlAny, &uart0_signal_rts);
#endif

#ifdef DDR_CTS0
	ssbi(DDR_CTS0);
	ccbi(PORT_CTS0);
#endif

	// enable interrupts
	sei();
}

void uart1Init(void)
{
	// initialize the buffers
	uart1InitBuffers();
	// initialize user receive handlers
	UartRxFunc[1] = 0;
	// enable RxD/TxD and interrupts

	outb(UCSR1B, BV(RXCIE)|BV(RXEN)|BV(TXEN));
	
	//outb(UCSR1A, inb(UCSR1A) | BV(U2X1));

	// set default baud rate
	uartSetBaudRate(1, UART1_DEFAULT_BAUD_RATE);
	// initialize states
	uartReadyTx[1] = TRUE;
	uartBufferedTx[1] = TRUE;
	// clear overflow count
	uartRxOverflow[1] = 0;
	// enable interrupts
	sei();
}

void uart1Check(void)
{
	if (!(inb(UCSR1B) & BV(RXCIE)))
	{
		outb(UCSR1B, inb(UCSR1B) | BV(RXCIE));
		uartFlushReceiveBuffer(1);
	}
}

#define uart1DisableRx	outb(UCSR1B, inb(UCSR1B) & ~BV(RXCIE))

void uart0InitBuffers(void)
{
	#ifndef UART_BUFFERS_EXTERNAL_RAM
		// initialize the UART0 buffers
		//bufferInit(&uartRxBuffer[0], uart0RxData, UART0_RX_BUFFER_SIZE);
		// Initialise the RX Buffer
		typRxBuffer0.pchWrite = typRxBuffer0.uchData;
		typRxBuffer0.ushLength = 0;

		bufferInit(&uartTxBuffer[0], uart0TxData, UART0_TX_BUFFER_SIZE);
	#else
		// initialize the UART0 buffers
		bufferInit(&uartRxBuffer[0], (uint8_t*) UART0_RX_BUFFER_ADDR, UART0_RX_BUFFER_SIZE);
		bufferInit(&uartTxBuffer[0], (uint8_t*) UART0_TX_BUFFER_ADDR, UART0_TX_BUFFER_SIZE);
	#endif
}

void uart1InitBuffers(void)
{
	#ifndef UART_BUFFERS_EXTERNAL_RAM
		// initialize the UART1 buffers
		bufferInit(&uartRxBuffer[1], uart1RxData, UART1_RX_BUFFER_SIZE);
		bufferInit(&uartTxBuffer[1], uart1TxData, UART1_TX_BUFFER_SIZE);
	#else
		// initialize the UART1 buffers
		bufferInit(&uartRxBuffer[1], (uint8_t*) UART1_RX_BUFFER_ADDR, UART1_RX_BUFFER_SIZE);
		bufferInit(&uartTxBuffer[1], (uint8_t*) UART1_TX_BUFFER_ADDR, UART1_TX_BUFFER_SIZE);
	#endif
}

void uartSetRxHandler(uint8_t nUart, void (*rx_func)(unsigned char c))
{
	// make sure the uart number is within bounds
	if(nUart < 2)
	{
		// set the receive interrupt to run the supplied user function
		UartRxFunc[nUart] = rx_func;
	}
}

void uartSetBaudRate(uint8_t nUart, u32 baudrate)
{
	// calculate division factor for requested baud rate, and set it
	uint8_t baudrateDiv;
	
	baudrateDiv = (uint8_t)((F_CPU+(baudrate*8L))/(baudrate*16L)-1);

	switch (nUart)
	{
	case 0:
		outb(UBRR0L, baudrateDiv);
		break;
	case 1:
		outb(UBRR1L, baudrateDiv);
		break;
#ifdef atmega1280
	case 2:
		outb(UBRR2L, baudrateDiv);
		break;
	case 3:
		outb(UBRR3L, baudrateDiv);
		break;
#endif
	}
}

cBuffer* uartGetRxBuffer(uint8_t nUart)
{
	// return rx buffer pointer
	return &uartRxBuffer[nUart];
}

cBuffer* uartGetTxBuffer(uint8_t nUart)
{
	// return tx buffer pointer
	return &uartTxBuffer[nUart];
}

void uartSendByte(uint8_t nUart, uint8_t txData)
{
	// wait for the transmitter to be ready
//	while(!uartReadyTx[nUart]);
	// send byte
	if(nUart)
	{
		while(!(UCSR1A & (1<<UDRE)));
		outb(UDR1, txData);
	}
	else
	{
		while(!(UCSR0A & (1<<UDRE)));
		outb(UDR0, txData);
	}
	// set ready state to FALSE
	uartReadyTx[nUart] = FALSE;
}

void uart0SendByte(uint8_t data)
{
	// send byte on UART0
	uartSendByte(0, data);
}

void uart1SendByte(uint8_t data)
{
	// send byte on UART1
	uartSendByte(1, data);
}

int uart0GetByte(void)
{
	// get single byte from receive buffer (if available)
	uint8_t c;
	if(uartReceiveByte(0,&c))
		return c;
	else
		return -1;
}

int uart1GetByte(void)
{
	// get single byte from receive buffer (if available)
	uint8_t c;
	if(uartReceiveByte(1,&c))
		return c;
	else
		return -1;
}

unsigned int uartGetSize(uint8_t nUart)
{
	// make sure we have a receive buffer
	if(uartRxBuffer[nUart].size)
		return uartRxBuffer[nUart].datalength;
	else
		return 0;
}

uint8_t uartReceiveByte(uint8_t nUart, uint8_t* rxData)
{
	// make sure we have a receive buffer
	if(uartRxBuffer[nUart].size)
	{
		// make sure we have data
		if(uartRxBuffer[nUart].datalength)
		{
			// get byte from beginning of buffer
			*rxData = bufferGetFromFront(&uartRxBuffer[nUart]);
			return TRUE;
		}
		else
			return FALSE;			// no data
	}
	else
		return FALSE;				// no buffer
}

void uartFlushSendBuffer(uint8_t nUart)
{
	bufferFlush(&uartTxBuffer[nUart]);
}

void uartFlushReceiveBuffer(uint8_t nUart)
{
	// flush all data from receive buffer
	uartRxStatus[nUart] = 0;

	if (nUart == 0x00)
	{
		typRxBuffer0.ushBytes = 0x00;
		typRxBuffer0.ushLength = 0;
		typRxBuffer0.pchWrite = typRxBuffer0.uchData;
		//typRxBuffer0.vptrRcvFunc = &uart0_frame_rcv_step0;
	}
	else if (nUart == 0x01)
	{
		bufferFlush(&uartRxBuffer[nUart]);
	}
}

uint8_t uartReceiveBufferIsEmpty(uint8_t nUart)
{
	return (uartRxBuffer[nUart].datalength == 0);
}

void uartAddToTxBuffer(uint8_t nUart, uint8_t data)
{
	// add data byte to the end of the tx buffer
	bufferAddToEnd(&uartTxBuffer[nUart], data);
}

void uart0AddToTxBuffer(uint8_t data)
{
	uartAddToTxBuffer(0,data);
}

void uart1AddToTxBuffer(uint8_t data)
{
	uartAddToTxBuffer(1,data);
}

void uartSendTxBuffer(uint8_t nUart)
{
	// turn on buffered transmit
	uartBufferedTx[nUart] = TRUE;
	if ((unsigned short)uartTxBuffer[nUart].datalength)
	{
		if (nUart)
			outb(UCSR1B, inb(UCSR1B) | BV(UDRIE1));
		else
			outb(UCSR0B, inb(UCSR0B) | BV(UDRIE0));
		//uartSendByte(nUart, bufferGetFromFront(&uartTxBuffer[nUart]));
	}
	//return;
	// send the first byte to get things going by interrupts
	
	//{	}
}

void uartAddToBufferCRC(uint8_t nUart, unsigned char *buffer, u16 nBytes, unsigned char *buffer2, u16 nBytes2, u16 crc)
{
	if((uartTxBuffer[nUart].datalength + nBytes2 + nBytes + 4 < uartTxBuffer[nUart].size) && nBytes)
	{
		cli();
		bufferAddBufferToEndUnSafe(&uartTxBuffer[nUart], buffer, nBytes);
		bufferAddBufferToEndUnSafeCrc16(&uartTxBuffer[nUart], buffer2, nBytes2, crc);
		sei();
	}
}

void uartAddToBuffer(uint8_t nUart, unsigned char *buffer, u16 nBytes)
{
	if((uartTxBuffer[nUart].datalength + nBytes  < uartTxBuffer[nUart].size) && nBytes)
	{
		cli();
		bufferAddBufferToEndUnSafe(&uartTxBuffer[nUart], buffer, nBytes);
		sei();
	}
}

uint8_t uartSendBuffer(uint8_t nUart, unsigned char *buffer, u16 nBytes)
{
	// check if there's space (and that we have any bytes to send at all)
	if((uartTxBuffer[nUart].datalength + nBytes) < uartTxBuffer[nUart].size && nBytes)
	{
		// Add the bytes to the buffer
		cli();
		bufferAddBufferToEndUnSafe(&uartTxBuffer[nUart], buffer, nBytes);
		sei();

		// Enabled the UDR data interrupt for the uart
		if (nUart)
			outb(UCSR1B, inb(UCSR1B) | BV(UDRIE1));
		else
		{
#ifdef PIN_RTS
			// Check RTS Status first
			if (!bit_is_clr(PIN_RTS))
#endif
			outb(UCSR0B, inb(UCSR0B) | BV(UDRIE0));
		}

		return TRUE;
	}

	return FALSE;

}

// UART Transmit Complete Interrupt Function
void uartTransmitService(uint8_t nUart)
{
	// check if buffered tx is enabled
	if(uartBufferedTx[nUart])
	{
		// check if there's data left in the buffer
		if(uartTxBuffer[nUart].datalength)
		{
			// send byte from top of buffer
			if(nUart)
				outb(UDR1,  bufferGetFromFront(&uartTxBuffer[1]) );
			else
				outb(UDR0,  bufferGetFromFront(&uartTxBuffer[0]) );
		}
		else
		{
			// no data left
			uartBufferedTx[nUart] = FALSE;
			// return to ready state
			uartReadyTx[nUart] = TRUE;
		}
	}
	else
	{
		// we're using single-byte tx mode
		// indicate transmit complete, back to ready
		uartReadyTx[nUart] = TRUE;
	}
}

/* find the consult request bytes to send given the command request position\
// position is zero based 
*/
unsigned char consultbyte(uint8_t position)
{
	uint16_t i;
	uint16_t byCount = 0;

	for(i=0;i<32;i++)
	{
		if ((uartConsultBitSet >> i) & (uint32_t)0x01)
		{
			byCount++;
		}
		if ((byCount-1) == position)
		{
			return i;
		}
	}
	return 0xFF;
}

void consultbyteNullify(uint8_t position)
{
	uint16_t i;
	uint16_t byCount = 0;

	for(i=0;i<32;i++)
	{
		if ((uartConsultBitSet >> i) & (uint32_t)0x00000001)
		{
			byCount++;
		}
		if ((byCount-1) == position)
		{
			uartConsultBitSet &= ((uint32_t)0xFFFFFFFF ^ ((uint32_t)0x00000001 << i));
			return;
		}
	}
}

uint8_t* getUartRxStatus(uint8_t nUart)
{
	return &uartRxStatus[nUart];
}

uint16_t* getUartCounter(uint8_t nUart)
{
	return &uartCounter[nUart];
}

void setUartConsultBitSet(uint32_t BitSet)
{
	uartConsultBitSet = BitSet;
}

void setUartConsultBytesExpected(uint8_t* Count)
{
	uartConsultExpected = *Count;
}

// set the consult bypass mode, and the first char to look for
void setUartConsultBypassState(uint8_t* Mode, uint8_t* FirstByte)
{
	uartConsultFirstByte = *FirstByte ^ 0xFF;
	uartConsultMode = *Mode;
}

inline int16_t recvchar(void)
{
	uint16_t timeOut = 0;
	while (!(UCSR0A & (1<<RXC0)))
	{
		timeOut++;
		wdt_reset();
		if (timeOut >= 0xFFFE)
		{
			return -1;
		}
	}
	return UDR0;
}

inline int16_t recvchar1(void)
{
	uint16_t timeOut = 0;
	while (!(UCSR1A & (1<<RXC0)))
	{
		timeOut++;
		wdt_reset();
		if (timeOut >= 0xFFFE)
		{
			return -1;
		}
	}
	return UDR1;

}

//UART_INTERRUPT_HANDLER
SIGNAL(SIG_UART0_TRANS)      
{
	// service UART0 transmit interrupt
	uartTransmitService(0);
}

SIGNAL(SIG_UART1_TRANS)      
{
	// service UART1 transmit interrupt
	uartTransmitService(1);
}

void uart0Check(void)
{
	if (typRxBuffer0.ushLength == 0)
	{
		if ( typRxBuffer0.uchData[0] != 0xAA )
			uartFlushReceiveBuffer(0);
//		else if (typRxBuffer0.uchData[1] != 0xA5)
//			uartFlushReceiveBuffer(0);
		else if (typRxBuffer0.ushBytes >= 0x06)
		{
			if (typRxBuffer0.uchData[1] != 0xA5)
			{
				uartFlushReceiveBuffer(0);
			}
			else
			{
				typRxBuffer0.ushLength = ((unsigned short)typRxBuffer0.uchData[4] << 8 | typRxBuffer0.uchData[5]) + 10;

				if (typRxBuffer0.ushLength > UART0_RX_BUFFER_SIZE)
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_TOOBIG);
				}
			}
		}
	}
	else if ( typRxBuffer0.ushBytes >= typRxBuffer0.ushLength )
	{
		uartRxStatus[0] = 0xFF;
		FrameCommand(typRxBuffer0.uchData);
		uartFlushReceiveBuffer(0);
	}
}
/*
volatile unsigned char ucChecking = 1;
// Naked Signal Trial  
SIGNAL(SIG_UART0_RECV)  
{
#ifdef PORT_CTS0
	ssbi(PORT_CTS0);
#endif

	typRxBuffer0.uchData[typRxBuffer0.ushBytes] = inb(UDR0);
	typRxBuffer0.ushBytes++;

	outb(TCNT2, 0x00);
	uart1DisableRx;

#ifdef PORT_CTS0
	ccbi(PORT_CTS0);
#endif

	// Check Inputs
	if (ucChecking)
	{
		ucChecking = 0;
		sei();
		uart0Check();
		ucChecking = 1;
	}
}*/

#define UART_TIMEOUT 0x0400

SIGNAL(SIG_UART0_RECV)  
{
//	typRxBuffer0.vptrRcvFunc();
	//uart0SendByte(typRxBuffer0.uchData[typRxBuffer0.ushLength-1]);
	
	register unsigned char	uchIn = inb(UDR0);
	//register unsigned char	uchStatus = uartRxStatus[0];

	if ( uartRxStatus[0] < 0xFF )
	{
		if ( uartRxStatus[0] < 0x01 )
		{
			if (uchIn == 0xAA)
			{
				uartRxStatus[0]++;
				*typRxBuffer0.pchWrite++ = uchIn;

				outb(TCNT2, 0x00);
				uart1DisableRx;
				return;
			}
			else
				return;
		}
		else if ( uartRxStatus[0] == 0x01 )
		{
			if (uchIn == 0xA5)
			{
				unsigned short	ushBytes = 0;
				register unsigned short	uchTimeout;

				uartRxStatus[0]++;
				*typRxBuffer0.pchWrite++ = uchIn;
				// Do Read Loop here!

				// Reset Timeout------------------------------- FROM
				uchTimeout = UART_TIMEOUT;
				while (!(UCSR0A & BV(RXC0)) && --uchTimeout)
					wdt_reset();
				if ((UCSR0A & BV(RXC0)))
					*typRxBuffer0.pchWrite++ = inb(UDR0);
				else
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_INCOMPLETE);
					return;
				}

				// Reset Timeout------------------------------- To
				uchTimeout = UART_TIMEOUT;
				while (!(UCSR0A & BV(RXC0)) && --uchTimeout)
					wdt_reset();
				if ((UCSR0A & BV(RXC0)))
					*typRxBuffer0.pchWrite++ = inb(UDR0);
				else
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_INCOMPLETE);
					return;
				}

				// Reset Timeout------------------------------- Bytes[1]
				uchTimeout = UART_TIMEOUT;
				while (!(UCSR0A & BV(RXC0)) && --uchTimeout)
					wdt_reset();
				if ((UCSR0A & BV(RXC0)))
				{
					*typRxBuffer0.pchWrite = inb(UDR0);
					ushBytes = (unsigned short)*typRxBuffer0.pchWrite++ << 8;
				}
				else
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_INCOMPLETE);
					return;
				}

				// Reset Timeout------------------------------ Bytes[0]
				uchTimeout = UART_TIMEOUT;
				while (!(UCSR0A & BV(RXC0)) && --uchTimeout)
					wdt_reset();
				if ((UCSR0A & BV(RXC0)))
				{
					*typRxBuffer0.pchWrite = inb(UDR0);
					ushBytes |= (unsigned short)*typRxBuffer0.pchWrite++;
					ushBytes += HEADERS_SIZE - 6;
				}
				else
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_INCOMPLETE);
					return;
				}

				// Check Length
				if (ushBytes > UART0_RX_BUFFER_SIZE)
				{
					uartFlushReceiveBuffer(0);
					FrameResponse(CMD_TOOBIG);
					return;
				}

				// Read in the entire packet
				do
				{
					uchTimeout = UART_TIMEOUT;
					while (!(UCSR0A & BV(RXC0)) && --uchTimeout)
						wdt_reset();
					if ((UCSR0A & BV(RXC0)))
						*typRxBuffer0.pchWrite++ = inb(UDR0);
					else
					{
						uartFlushReceiveBuffer(0);
						FrameResponse(CMD_INCOMPLETE);
						return;
					}
				} while (--ushBytes);

				uartRxStatus[0] = 0xFF;
				FrameCommand(typRxBuffer0.uchData);
				uartFlushReceiveBuffer(0);
				//uartRxStatus[0] = 0;
			}
			else
				uartFlushReceiveBuffer(0);
		}
		else
		{
			uartFlushReceiveBuffer(0);
		}
	}
}
/*	
	if (uartRxStatus[0] < 255)
	{
		//bufferAddToEnd(&uartRxBuffer[0], c);
		typRxBuffer0.uchData[typRxBuffer0.ushBytes++] = c;
		//if( !bufferAddToEnd(&uartRxBuffer[0], c) )
		//{
		//	uartRxOverflow[0]++;
		//	uartFlushReceiveBuffer(0);
		//} else 
		//{  //No Buffer Overflow, so parse the character thats now in the buffer
		if (uartRxStatus[0] < 6)
		{
			switch (uartRxStatus[0])
			{
				case 0x00:
					if (c == 0xAA)
						uartRxStatus[0]++;
					else
					{
						uartFlushReceiveBuffer(0);
						return;
					}
					break;
				case 0x01:
					if (c == 0xA5)
						uartRxStatus[0]++;
					else
					{
						uartFlushReceiveBuffer(0);
						return;
					}
					break;
				case 0x02:
					uartRxStatus[0]++;
					break;
				case 0x03:
					uartRxStatus[0]++;
					break;
				case 0x04:
					uartRxStatus[0]++;
					uartRxBytes[0] = 0;
					uartRxBytes[0] = ((uint16_t)c) << 8;
					break;
				case 0x05:
					uartRxStatus[0]++;
					uartRxBytes[0] |= c;
					uartRxBytes[0] += HEADERS_SIZE;

					if (uartRxBytes[0] > UART0_RX_BUFFER_SIZE)
					{
						uartFlushReceiveBuffer(0);
						FrameResponse(CMD_TOOBIG);
						return;
					}

					// Now recieve the entire packet - Note: Looses sync if interupt driven past the 8-10ths bytes. Must now read in entire packet... sucks but ye...
					{
						register unsigned short i;
						for (i=0;i<uartRxBytes[0]-6;i++)
						{
							if ((c = recvchar())== -1)
							{
								uartFlushReceiveBuffer(0);
								return;
							}
							else
							{
								typRxBuffer0.uchData[typRxBuffer0.ushBytes++] = c;
								outb(TCNT2, 0x00);
							}
								//bufferAddToEndUnSafe(&uartRxBuffer[0], (uint8_t)rcv); 
						}
					}
					uartRxStatus[0] = 0xFF;
					//timer2Off();
					FrameCommand(typRxBuffer0.uchData);
					uartRxStatus[0] = 0;
					//timer2On();
					break;
			}
		}
		else
		{
			uartFlushReceiveBuffer(0);
			return;
		}
		//}
	}
}*/

/* This function taks on the STD BikiUsb header, footer and calcualtes the CRC for the frame
*/
inline void FrameHeadFootCrc(uint8_t* Buffer, uint16_t* Length)
{
	Buffer[0] = 0xAA;
	Buffer[1] = 0xA5;
	Buffer[2] = ID_PC;
	Buffer[3] = ID_ATMEL;
	Buffer[4] = ((*Length - HEADERS_SIZE) >> 8) & 0xFF;
	Buffer[5] = (*Length - HEADERS_SIZE) & 0xFF;
	Buffer[*Length - 2] = 0x55;
	Buffer[*Length - 1] = 0x5A;
	crcGenerate(&Buffer[0], *Length);
}



SIGNAL(SIG_UART1_RECV)      
{
	// service UART1 receive interrupt
	register unsigned char c = inb(UDR1);;
	unsigned char cmd[2] = {0x5A, 0};
	unsigned char go = 0xF0;
	register unsigned char i;

	//uartSendByte(0,c);
	//uart0SendByte(c);
	// if there's a user function to handle this receive event
	if(UartRxFunc[1])
	{
		if (uartConsultMode == uConModeSeach)
		{
			if (c == uartConsultFirstByte)
			{
				uartConsultMode = uConModeStream;
			}
			else
			{
				uartFlushReceiveBuffer(1);
				return;
			}
		}
		// Dont actualy call the funciton, just use it to signfiy the pass through
		bufferAddToEnd(&uartRxBuffer[1], c);
		if ( uartRxBuffer[1].datalength >= uartConsultExpected )
		{
			uint16_t Length = uartConsultExpected + HEADERS_SIZE;
			uint8_t Buffer[Length];
			for (i=6;i<uartConsultExpected+6;i++)
				{ Buffer[i] = bufferGetFromFront(&uartRxBuffer[1]);}
			uartFlushReceiveBuffer(1);
			FrameHeadFootCrc(Buffer,&Length);
			Buffer[3] = ID_ECU;
			uartSendBuffer(0,Buffer, Length);
		}
	} 
	else 	if (uartRxStatus[1] == 2)
	{
		bufferAddToEnd(&uartRxBuffer[1], c);
		// check if the number of bytes in the buffer is greater than or equale to the number required for a packet
		if (uartRxBuffer[1].datalength >= (uartConsultExpected + 4))
		{
			if (uart1RxData[uartConsultExpected+2] == 0xFF &&
				uart1RxData[uartConsultExpected+3] == uartConsultExpected)
			{
				setConsultPacket(uart1RxData, uartConsultExpected+2,&uartConsultBitSet);
				
				uartFlushReceiveBuffer(1);
				bufferAddToEnd(&uartRxBuffer[1], 0xFF);
				bufferAddToEnd(&uartRxBuffer[1], c);
				uartCounter[1]++;
				uartRxStatus[1] = 2;
			} else {
				uartFlushReceiveBuffer(1);
			}
			return;
		}
	} 
	else
	{
		// Handle the Complted Secondary Consult Uart here
		switch (uartRxStatus[1])
		{
			case 0x00: // consult already initialised, searching for 0xFF header
				if (c == 0xFF)
				{ 
					uartRxStatus[1]++; 
					bufferAddToEnd(&uartRxBuffer[1], c);
				} 
				else
					{ uartFlushReceiveBuffer(1); }
				break;
			case 0x01: // consult already initialised, searching for 0xXX bytes after header
				if (c == uartConsultExpected)
					{ 
						uartRxStatus[1]++; 
						bufferAddToEnd(&uartRxBuffer[1], c);
					} 
				else
					{ uartFlushReceiveBuffer(1); }
				break;
			case 0x10: // consult not initialised, searching for an 0x10 signifying consult init OK, a byte of 0x00 is ignored and cleared
				if (c == 0x10)
				{
					cmd[1] = consultbyte(0);
					if (cmd[1] != 0xFF)
					{
						uartSendBuffer(1, &cmd[0], 2);
						uartRxStatus[1] += 2;
						uartConsultExpected = 1;
					}
					else
					{
						uartSendBuffer(1, &go, 1);
						uartRxStatus[1] = 0x00;
					}
				}
				else
				{
					uartFlushReceiveBuffer(1);
					uartRxStatus[1] = 0x10;
				}
				uartCounter[1]++;
				break;
			case 0x11:	// 0xFF recieved from consult bus, its now time to parse the desired consult request command byte by byte, recieve and increment the status
				cmd[1] = consultbyte(uartRxStatus[1] - 0x11);
				if (cmd[1] != 0xFF)
				{
					uartSendBuffer(1, &cmd[0], 2);
					uartRxStatus[1]++;
					uartConsultExpected = 1;
				}
				else
				{
					uartSendBuffer(1, &go, 1);
					uartRxStatus[1] = 0x00;
				}
				uartCounter[1]++;
				break;
			default:
				if ((uartRxStatus[1] >= 0x12) && (uartRxStatus[1] <= 0x30))
				{
					// Recieve the reponse from the previous command, if its all Hunky Dory then continue oh! expecting 0xA5 0xYY if you recieve only 0xA5 0xEF then thats an error.
					// Remove that bit set from the atmel's SRam holder of the EEprom Consult Bit Set.
					if (c == 0xFE)
					{
						consultbyteNullify(uartRxStatus[1] - 0x12);
						uartRxStatus[1] = 0x11;
					} else if (c != 0xA5)
					{
						cmd[1] = consultbyte(uartRxStatus[1] - 0x11);
						if ((cmd[1] != 0xFF) && (uartConsultExpected < 0x10))
						{
							uartSendBuffer(1, &cmd[0], 2);
							uartRxStatus[1]++;
							uartConsultExpected++;
						}
						else
						{
							for (i=0;i<0x10;i++)
							{ consultbyteNullify(0x10); }
							uartSendBuffer(1, &go, 1);
							uartRxStatus[1] = 0x00;
						}
					}
				}
				uartCounter[1]++;
				break;
		}
	}
}

void uart0_signal_rts ( unsigned char state )
{
	if (state)
	{
		if (uartTxBuffer[0].datalength)
		{
			// Enable the Sending Interrupt
			outb(UCSR0B, inb(UCSR0B) | BV(UDRIE0));
		}
	}
	else
	{
		// Disable the Sending Interrupt
		outb(UCSR0B, inb(UCSR0B) & ~BV(UDRIE0));
	}
}

SIGNAL(SIG_UART0_DATA)
{
	// Write out the very first byte from buffer
	outb(UDR0, bufferGetFromFront(&uartTxBuffer[0]));

	if (uartTxBuffer[0].datalength <= 0)
	{
		uartTxBuffer[0].datalength = 0;
		outb(UCSR0B, inb(UCSR0B) & ~BV(UDRIE0));
		bufferFlush(&uartTxBuffer[0]);
	}
}

SIGNAL(SIG_UART1_DATA)
{
	// Write out the very first byte from buffer
	outb(UDR1, bufferGetFromFront(&uartTxBuffer[1]));

	if (uartTxBuffer[1].datalength == 0)
		outb(UCSR1B, inb(UCSR1B) & ~BV(UDRIE1));
}
